import pynput
from functools import wraps
from time import perf_counter, sleep
from threading import Event,Lock
from _io import TextIOWrapper
from json import dumps

start_time: float
file: TextIOWrapper
done: Event
lock=Lock()

def write_to_file(func):
    global file
    @wraps(func)
    def _check_exit(*_args, **_kwargs):
        data = func(*_args, **_kwargs)
        now = round(perf_counter() - start_time, 6)
        lock.acquire()
        print('\r正在录制:' + str(now)+'s', end='', flush=True)
        data = {'time': now, **data}  # 使时间戳位于文件第一列，便于阅读
        # data['time'] = now
        file.write(dumps(data) + '\n')
        lock.release()
    return _check_exit


@write_to_file
def mouse_on_move(x, y, *args):
    global start_time
    data = {'type': 'move',
            'x': x,
            'y': y}
    return data


@write_to_file
def mouse_on_click(x, y, button, pressed, *args):
    global start_time
    data = {'type': 'click',
            'x': x,
            'y': y,
            'button': button.name,
            'pressed': pressed}
    return data


@write_to_file
def mouse_on_scroll(x, y, dx, dy, *args):
    global start_time
    data = {'type': 'scroll',
            'x': x,
            'y': y,
            'dx': dx,
            'dy': dy}
    return data


@write_to_file
def keyboard_on_press(key, *args):
    global start_time
    if isinstance(key, pynput.keyboard.Key):
        data = {'type': 'press',
                'key_type': 'Key',
                'key': key.name}
    elif isinstance(key, pynput.keyboard.KeyCode):
        data = {'type': 'press',
                'key_type': 'KeyCode',
                'key': key.char}
    return data


@write_to_file
def keyboard_on_release(key, *args):
    global start_time
    if isinstance(key, pynput.keyboard.Key):
        data = {'type': 'release',
                'key_type': 'Key',
                'key': key.name}
    elif isinstance(key, pynput.keyboard.KeyCode):
        data = {'type': 'release',
                'key_type': 'KeyCode',
                'key': key.char}
    return data


def start_record(filename: str, _done: Event):
    global start_time, file, done
    
    done = _done
    file = open(filename, 'w+')
    start_time = perf_counter()
    
    mouse_listener = pynput.mouse.Listener(on_move=mouse_on_move, on_click=mouse_on_click, on_scroll=mouse_on_scroll)
    keyboard_listener = pynput.keyboard.Listener(on_press=keyboard_on_press, on_release=keyboard_on_release)
    mouse_listener.daemon = True
    keyboard_listener.daemon = True
    
    mouse_listener.start()
    keyboard_listener.start()
    
    while True:
        if done.wait(0.1):
            mouse_listener.stop()
            keyboard_listener.stop()
            sleep(0.05)  # 等待write_to_file()写完文件，避免文件损坏或在文件关闭之后写文件
            file.close()
            break


if __name__ == '__main__':
    _done = Event()
    
    
    def set_done():
        global done
        sleep(10)
        done.set()
        # sleep(2)
    
    
    import threading
    
    set_it = threading.Thread(target=set_done)
    set_it.start()
    start_record('../saves/1.txt', _done)
